package com.cloud.redis.api;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.lettuce.core.cluster.ClusterClientOptions;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePool;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

public class LettuceCreated extends CachingConfigurerSupport {
 
    private static int maxIdle=4;
    private static int minIdle=0;
    private static int maxTotal=3000;
    private static int timeout=4000;
    private static String nodes="192.168.110.129:6379";
    private static String password="123456";
    private static volatile  RedisTemplate<String, Object> redisTemplate=null;
    public static RedisTemplate<String, Object> getRedisTemplateInstance(){
        if (redisTemplate==null) {
            synchronized (LettuceCreated.class){
                if(redisTemplate==null){
                    redisTemplate=lettuceConnectionFactory();
                }
            }
        }
        return redisTemplate;
    }

    public static RedisTemplate<String, Object>  lettuceConnectionFactory() {
        // 连接池配置
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        // 线程池线程最大空闲数
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        // 线程池线程最小空闲数
        genericObjectPoolConfig.setMinIdle(minIdle);
        // 线程池最大线程数
        genericObjectPoolConfig.setMaxTotal(maxTotal);
        // 当连接池已用完时，客户端应该等待获取新连接的最大时间，单位为毫秒
        genericObjectPoolConfig.setMaxWaitMillis(timeout);
        genericObjectPoolConfig.setTestOnBorrow(false);
 
        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                // 关闭ping
                .pingBeforeActivateConnection(false)
                .build();
 
        LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
                .clientOptions(clusterClientOptions)
                // 超时时间
                .shutdownTimeout(Duration.ofMillis(timeout))
                .poolConfig(genericObjectPoolConfig)
                .build();
  //集群
        // redis集群节点ip:port  英文逗号隔开
//        if (StringUtils.isEmpty(nodes)) {
//            throw new RuntimeException();
//        }
//        String[] hostAndPorts = nodes.split(",");
//        Set<RedisNode> nodes = new HashSet<>();
//        for (String hostAndPort : hostAndPorts) {
//            String[] ipAndPort = hostAndPort.split(":");
//            nodes.add(new RedisNode(ipAndPort[0], Integer.parseInt(ipAndPort[1])));
//        }
//
//        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
//        redisClusterConfiguration.setClusterNodes(nodes);
//        redisClusterConfiguration.setMaxRedirects(nodes.size());
//        redisClusterConfiguration.setPassword(RedisPassword.of(password));
        //单机
        RedisStandaloneConfiguration redisStandaloneConfiguration=new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName("192.168.110.129");
        redisStandaloneConfiguration.setPort(6379);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        // 根据配置和客户端配置创建连接
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
        lettuceConnectionFactory.afterPropertiesSet();
 
        return redisTemplate(lettuceConnectionFactory);
    }
 
    public  static  RedisTemplate<String, Object> redisTemplate( LettuceConnectionFactory lettuceConnectionFactory ) {

        // 设置序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = jackson2JsonRedisSerializer();
        // 配置redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        // key序列化
        redisTemplate.setKeySerializer(jackson2JsonRedisSerializer());
        // value序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // Hash key序列化
        redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer());
        // Hash value序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

 
 
    private static Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper()
                .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY).enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL));
        return jackson2JsonRedisSerializer;
    }

    public static void main(String[] args) {

    }
}
 